package com.github.bobjoy.java.thread.concurrent.atomic;

import com.github.bobjoy.java._common.Person;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceDemo {

    // 普通引用
    private static Person person1;

    @Test
    public void testCustomReference() throws InterruptedException {
        person1 = new Person("Tom", 18);

        System.out.println("Person is " + person1.toString());

        Thread t1 = new Thread(new Task1());
        Thread t2 = new Thread(new Task2());

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Now Person is " + person1.toString());
    }

    class Task1 implements Runnable {
        public void run() {
            person1.setAge(person1.getAge() + 1);
            person1.setName("Tom1");

            System.out.println("Thread1 Values " + person1.toString());
        }
    }

    class Task2 implements Runnable {
        public void run() {
            person1.setAge(person1.getAge() + 2);
            person1.setName("Tom2");

            System.out.println("Thread2 Values " + person1.toString());
        }
    }

    /////////////////////////////////////////////////////////////////////////////

    // 原子性引用
    private static AtomicReference<Person> person2;

    @Test
    public void testAtomicReference() throws InterruptedException {
        person2 = new AtomicReference<>(new Person("Tom", 18));

        System.out.println("Atomic Person is " + person2.get().toString());

        Thread t1 = new Thread(new Task3());
        Thread t2 = new Thread(new Task4());

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Now Atomic Person is " + person2.get().toString());
    }

    class Task3 implements Runnable {
        public void run() {
            person2.getAndSet(new Person("Tom1", person2.get().getAge() + 1));

            System.out.println("Thread1 Atomic References " + person2.get().toString());
        }
    }

    class Task4 implements Runnable {
        public void run() {
            person2.getAndSet(new Person("Tom2", person2.get().getAge() + 2));

            System.out.println("Thread2 Atomic References " + person2.get().toString());
        }
    }

}
